Introduction¶

  • Aim of this notebook is to run Vanilla CNN and Fine-Tune VGG16 - for Dogs and Cats Classification using tensorflow.

Obtaining the Data¶

Load the images folders & required libraries¶

In [ ]:
from tensorflow import keras
from tensorflow.keras import layers
from keras.callbacks import ModelCheckpoint
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import seaborn as sns
import pandas as pd
import warnings
warnings.filterwarnings('ignore')

import os, shutil, pathlib

train_dir = pathlib.Path("data/train")
new_base_dir = pathlib.Path("datacats_and_dogs_small")


def make_subset(subset_name, start_index, end_index):
    for category in ("cat", "dog"):
        dir = new_base_dir / subset_name / category
        os.makedirs(dir)
        fnames = [f"{category}.{i}.jpg" for i in range(start_index, end_index)]
        for fname in fnames:
            shutil.copyfile(src=train_dir / fname,
                            dst=dir / fname)

make_subset("train", start_index=0, end_index=1000)
make_subset("validation", start_index=1000, end_index=1500)
make_subset("test", start_index=1500, end_index=2500)

Create Datasets for Images¶

In [ ]:
from tensorflow.keras.utils import image_dataset_from_directory


data_folder = pathlib.Path('datacats_and_dogs_small')


train_dataset = image_dataset_from_directory(
    data_folder / "train",
    image_size=(180, 180),
    batch_size=32)
validation_dataset = image_dataset_from_directory(
    data_folder / "validation",
    image_size=(180, 180),
    batch_size=32)
test_dataset = image_dataset_from_directory(
    data_folder / "test",
    image_size=(180, 180),
    batch_size=32)
Found 2000 files belonging to 2 classes.
Found 1000 files belonging to 2 classes.
Found 2000 files belonging to 2 classes.
In [ ]:
type(train_dataset)
Out[ ]:
tensorflow.python.data.ops.batch_op._BatchDataset
In [ ]:
for data_batch, labels_batch in train_dataset:
    print("data batch shape:", data_batch.shape)
    print("labels batch shape:", labels_batch.shape)
    break
data batch shape: (32, 180, 180, 3)
labels batch shape: (32,)
In [ ]:
import matplotlib.pyplot as plt

plt.imshow(data_batch[0].numpy().astype("uint8"))
Out[ ]:
<matplotlib.image.AxesImage at 0x2e527db6c50>

Exploratory Data Analysis¶

  • Aim of this section is to explore the dataset in some depth. This includes looking at some examples of each image, exploring the distribution of cat vs dog classes, and studying the image dimensions.

Display First 10 Cats & Dogs Images¶

In [ ]:
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

cols = 5
rows = 2  
fig = plt.figure(figsize=(4 * cols - 1, 4.5 * rows - 1))
for i in range(1, 11):
    img_path = f'datacats_and_dogs_small/train/cat/cat.{i}.jpg'  
    img = mpimg.imread(img_path)
    ax = fig.add_subplot(rows, cols, i)
    ax.imshow(img)
    ax.set_title(f'Cat {i}')
    ax.axis('off') 
fig.suptitle('First 10 Cat Images', fontsize=16)  
plt.tight_layout() 
plt.show()
plt.close()

fig = plt.figure(figsize=(4 * cols - 1, 4.5 * rows - 1))
for i in range(1, 11):
    img_path = f'datacats_and_dogs_small/train/dog/dog.{i}.jpg'  
    img = mpimg.imread(img_path)
    ax = fig.add_subplot(rows, cols, i)
    ax.imshow(img)
    ax.set_title(f'Cat {i}')
    ax.axis('off') 
fig.suptitle('First 10 Dog Images', fontsize=16)  
plt.tight_layout() 
plt.show()
plt.close()

Frequency of Cats & Dogs in Training Set¶

In [ ]:
total_cats = len(os.listdir('datacats_and_dogs_small/train/cat'))
total_dogs = len(os.listdir('datacats_and_dogs_small/train/dog'))

pd.DataFrame({'category': ['cat', 'dog'], 'count': [total_cats, total_dogs]}).plot.bar(x='category', y='count', legend=False)
Out[ ]:
<Axes: xlabel='category'>
  • Both Cats & Dogs have equal number images which indicates a balanced dataset.

Image Dimensions¶

In [ ]:
# function to get image dimensions
def get_image_dimensions(folder_path):
    image_dimensions = []
    for filename in os.listdir(folder_path):
        if filename.endswith('.jpg') or filename.endswith('.jpg'):
            image_path = os.path.join(folder_path, filename)
            img = mpimg.imread(image_path)
            if img is not None:  
                height, width, _ = img.shape
                image_dimensions.append((filename, width, height))
    return image_dimensions

cat_folder_path = 'datacats_and_dogs_small/train/cat'
dog_folder_path = 'datacats_and_dogs_small/train/dog'
# tuples with dimensions of images
cat_dimensions = get_image_dimensions(cat_folder_path)
dog_dimensions = get_image_dimensions(dog_folder_path)

# Convert the list of tuples to a DataFrame
cat_df = pd.DataFrame(cat_dimensions, columns=['filename', 'width', 'height'])
dog_df = pd.DataFrame(dog_dimensions, columns=['filename', 'width', 'height'])

1. Distribution of Heights¶

In [ ]:
combined_height_df = pd.concat([
    cat_df[['height']].assign(image_type='cat'),
    dog_df[['height']].assign(image_type='dog')
])

fig = plt.figure(figsize=(12, 6))
sns.displot(data=combined_height_df, x='height', hue='image_type', kde=True,col='image_type', palette='viridis',legend=False)
plt.suptitle('Distribution of Heights of Cat and Dog Images', x=0.5, y=1.05, ha='center', fontsize=16) 
plt.show()
<Figure size 1200x600 with 0 Axes>

2. Distribution of Width¶

In [ ]:
combined_width_df = pd.concat([
    cat_df[['width']].assign(image_type='cat'),
    dog_df[['width']].assign(image_type='dog')
])

fig = plt.figure(figsize=(12, 6))
sns.displot(data=combined_width_df, x='width', hue='image_type', kde=True,col='image_type',legend=False)
plt.suptitle('Distribution of Widths of Cat and Dog Images', x=0.5, y=1.05, ha='center', fontsize=16) 
plt.show()
<Figure size 1200x600 with 0 Axes>

Model Creation¶

Model 1¶

In [ ]:
inputs = keras.Input(shape=(180, 180, 3))
x = layers.Rescaling(1./255)(inputs)
x = layers.Conv2D(filters=32, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=64, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=128, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation="relu")(x)
x = layers.MaxPooling2D(pool_size=2)(x)
x = layers.Conv2D(filters=256, kernel_size=3, activation="relu")(x)
x = layers.Flatten()(x)
outputs = layers.Dense(1, activation="sigmoid")(x)
model_1 = keras.Model(inputs=inputs, outputs=outputs)
In [ ]:
model_1.summary()
Model: "model_3"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_5 (InputLayer)        [(None, 180, 180, 3)]     0         
                                                                 
 rescaling_1 (Rescaling)     (None, 180, 180, 3)       0         
                                                                 
 conv2d_5 (Conv2D)           (None, 178, 178, 32)      896       
                                                                 
 max_pooling2d_4 (MaxPooling  (None, 89, 89, 32)       0         
 2D)                                                             
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_5 (InputLayer)        [(None, 180, 180, 3)]     0         
                                                                 
 rescaling_1 (Rescaling)     (None, 180, 180, 3)       0         
                                                                 
 conv2d_5 (Conv2D)           (None, 178, 178, 32)      896       
                                                                 
 max_pooling2d_4 (MaxPooling  (None, 89, 89, 32)       0         
 2D)                                                             
                                                                 
 conv2d_6 (Conv2D)           (None, 87, 87, 64)        18496     
                                                                 
 max_pooling2d_5 (MaxPooling  (None, 43, 43, 64)       0         
 2D)                                                             
                                                                 
 conv2d_7 (Conv2D)           (None, 41, 41, 128)       73856     
                                                                 
 max_pooling2d_6 (MaxPooling  (None, 20, 20, 128)      0         
 2D)                                                             
                                                                 
 conv2d_8 (Conv2D)           (None, 18, 18, 256)       295168    
                                                                 
 max_pooling2d_7 (MaxPooling  (None, 9, 9, 256)        0         
 2D)                                                             
                                                                 
 conv2d_9 (Conv2D)           (None, 7, 7, 256)         590080    
                                                                 
 flatten_3 (Flatten)         (None, 12544)             0         
                                                                 
 dense_5 (Dense)             (None, 1)                 12545     
                                                                 
=================================================================
Total params: 991,041
Trainable params: 991,041
Non-trainable params: 0
_________________________________________________________________
In [ ]:
model_1.compile(loss="binary_crossentropy",
              optimizer="rmsprop",
              metrics=["accuracy"])
In [ ]:
checkpoint_filepath = 'best_model_model1.hdf5' 

callbacks = [
    keras.callbacks.ModelCheckpoint(
        filepath=checkpoint_filepath,
        save_best_only=True,
        monitor="val_loss",
        mode='min')
]
history_1 = model_1.fit(
    train_dataset,
    epochs=30,
    validation_data=validation_dataset,
    callbacks=callbacks)
Epoch 1/30
63/63 [==============================] - 63s 994ms/step - loss: 0.1084 - accuracy: 0.9665 - val_loss: 1.1867 - val_accuracy: 0.7340
Epoch 2/30
63/63 [==============================] - 66s 1s/step - loss: 0.0711 - accuracy: 0.9735 - val_loss: 2.0890 - val_accuracy: 0.6980
Epoch 3/30
63/63 [==============================] - 68s 1s/step - loss: 0.0838 - accuracy: 0.9685 - val_loss: 1.4424 - val_accuracy: 0.7220
Epoch 4/30
63/63 [==============================] - 65s 1s/step - loss: 0.0570 - accuracy: 0.9840 - val_loss: 1.3466 - val_accuracy: 0.7440
Epoch 5/30
63/63 [==============================] - 76s 1s/step - loss: 0.0490 - accuracy: 0.9860 - val_loss: 1.2987 - val_accuracy: 0.7520
Epoch 6/30
63/63 [==============================] - 69s 1s/step - loss: 0.0692 - accuracy: 0.9765 - val_loss: 1.5693 - val_accuracy: 0.7560
Epoch 7/30
63/63 [==============================] - 65s 1s/step - loss: 0.0557 - accuracy: 0.9850 - val_loss: 1.5124 - val_accuracy: 0.7330
Epoch 8/30
63/63 [==============================] - 73s 1s/step - loss: 0.0456 - accuracy: 0.9850 - val_loss: 1.5896 - val_accuracy: 0.7310
Epoch 9/30
63/63 [==============================] - 59s 940ms/step - loss: 0.0362 - accuracy: 0.9875 - val_loss: 1.6021 - val_accuracy: 0.7410
Epoch 10/30
63/63 [==============================] - 58s 924ms/step - loss: 0.0309 - accuracy: 0.9905 - val_loss: 1.7103 - val_accuracy: 0.7440
Epoch 11/30
63/63 [==============================] - 60s 945ms/step - loss: 0.0388 - accuracy: 0.9905 - val_loss: 1.8422 - val_accuracy: 0.7460
Epoch 12/30
63/63 [==============================] - 59s 934ms/step - loss: 0.0667 - accuracy: 0.9810 - val_loss: 1.9422 - val_accuracy: 0.7300
Epoch 13/30
63/63 [==============================] - 62s 983ms/step - loss: 0.0267 - accuracy: 0.9925 - val_loss: 2.2143 - val_accuracy: 0.7340
Epoch 14/30
63/63 [==============================] - 74s 1s/step - loss: 0.0526 - accuracy: 0.9880 - val_loss: 2.1930 - val_accuracy: 0.7210
Epoch 15/30
63/63 [==============================] - 60s 945ms/step - loss: 0.0733 - accuracy: 0.9925 - val_loss: 2.5046 - val_accuracy: 0.6970
Epoch 16/30
63/63 [==============================] - 59s 936ms/step - loss: 0.0338 - accuracy: 0.9920 - val_loss: 2.2210 - val_accuracy: 0.7320
Epoch 17/30
63/63 [==============================] - 59s 940ms/step - loss: 0.0572 - accuracy: 0.9875 - val_loss: 2.9198 - val_accuracy: 0.7080
Epoch 18/30
63/63 [==============================] - 59s 937ms/step - loss: 0.0293 - accuracy: 0.9910 - val_loss: 2.6978 - val_accuracy: 0.7210
Epoch 19/30
63/63 [==============================] - 58s 916ms/step - loss: 0.0617 - accuracy: 0.9840 - val_loss: 2.6348 - val_accuracy: 0.7260
Epoch 20/30
63/63 [==============================] - 57s 911ms/step - loss: 0.0317 - accuracy: 0.9880 - val_loss: 2.7319 - val_accuracy: 0.7290
Epoch 21/30
63/63 [==============================] - 60s 950ms/step - loss: 0.0696 - accuracy: 0.9860 - val_loss: 2.8590 - val_accuracy: 0.7290
Epoch 22/30
63/63 [==============================] - 59s 941ms/step - loss: 0.0727 - accuracy: 0.9850 - val_loss: 2.5008 - val_accuracy: 0.7130
Epoch 23/30
63/63 [==============================] - 58s 914ms/step - loss: 0.0436 - accuracy: 0.9890 - val_loss: 2.6383 - val_accuracy: 0.7410
Epoch 24/30
63/63 [==============================] - 60s 944ms/step - loss: 0.0434 - accuracy: 0.9890 - val_loss: 2.6467 - val_accuracy: 0.7350
Epoch 25/30
63/63 [==============================] - 60s 944ms/step - loss: 0.0273 - accuracy: 0.9915 - val_loss: 2.9419 - val_accuracy: 0.7270
Epoch 26/30
63/63 [==============================] - 59s 939ms/step - loss: 0.0452 - accuracy: 0.9920 - val_loss: 2.6423 - val_accuracy: 0.7260
Epoch 27/30
63/63 [==============================] - 60s 954ms/step - loss: 0.0458 - accuracy: 0.9885 - val_loss: 2.5687 - val_accuracy: 0.7290
Epoch 28/30
63/63 [==============================] - 60s 945ms/step - loss: 0.0108 - accuracy: 0.9960 - val_loss: 3.2115 - val_accuracy: 0.7340
Epoch 29/30
63/63 [==============================] - 58s 921ms/step - loss: 0.0390 - accuracy: 0.9890 - val_loss: 2.9265 - val_accuracy: 0.7320
Epoch 30/30
63/63 [==============================] - 58s 922ms/step - loss: 0.0279 - accuracy: 0.9905 - val_loss: 3.3471 - val_accuracy: 0.7200

Plots for Evaluating the model¶

In [ ]:
accuracy = history_1.history["accuracy"]
val_accuracy = history_1.history["val_accuracy"]
loss = history_1.history["loss"]
val_loss = history_1.history["val_loss"]
epochs = range(1, len(accuracy) + 1)
plt.plot(epochs, accuracy, "bo", label="Training accuracy")
plt.plot(epochs, val_accuracy, "b", label="Validation accuracy")
plt.title("Training and validation accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, loss, "bo", label="Training loss")
plt.plot(epochs, val_loss, "b", label="Validation loss")
plt.title("Training and validation loss")
plt.legend()
plt.show()

Testing the model with test set¶

In [ ]:
test_model_1 = keras.models.load_model(
    "best_model_model1.hdf5")
test_loss_1, test_acc_1 = test_model_1.evaluate(test_dataset)
print(f"Test accuracy: {test_acc_1:.3f}")
63/63 [==============================] - 12s 182ms/step - loss: 1.1131 - accuracy: 0.7290
Test accuracy: 0.729
In [ ]:
history_1_dict = history_1.history
hist_df_1 = pd.DataFrame(history_1_dict)
hist_df_1
Out[ ]:
loss accuracy val_loss val_accuracy
0 0.108392 0.9665 1.186704 0.734
1 0.071110 0.9735 2.088961 0.698
2 0.083778 0.9685 1.442383 0.722
3 0.056978 0.9840 1.346597 0.744
4 0.048969 0.9860 1.298726 0.752
5 0.069178 0.9765 1.569296 0.756
6 0.055669 0.9850 1.512403 0.733
7 0.045553 0.9850 1.589638 0.731
8 0.036161 0.9875 1.602066 0.741
9 0.030858 0.9905 1.710316 0.744
10 0.038763 0.9905 1.842248 0.746
11 0.066738 0.9810 1.942221 0.730
12 0.026669 0.9925 2.214325 0.734
13 0.052570 0.9880 2.192991 0.721
14 0.073299 0.9925 2.504561 0.697
15 0.033810 0.9920 2.221050 0.732
16 0.057207 0.9875 2.919831 0.708
17 0.029309 0.9910 2.697770 0.721
18 0.061717 0.9840 2.634845 0.726
19 0.031745 0.9880 2.731930 0.729
20 0.069556 0.9860 2.858980 0.729
21 0.072734 0.9850 2.500825 0.713
22 0.043605 0.9890 2.638330 0.741
23 0.043441 0.9890 2.646658 0.735
24 0.027320 0.9915 2.941912 0.727
25 0.045223 0.9920 2.642344 0.726
26 0.045754 0.9885 2.568705 0.729
27 0.010794 0.9960 3.211460 0.734
28 0.038990 0.9890 2.926472 0.732
29 0.027892 0.9905 3.347083 0.720

Conclusions¶

Training & Validation loss

  • This model performs well on the training data but not on validation data.
  • The validation loss start to increase after epoch 5. The model have less loss until the epoch 5.
  • The gap between validation and training loss is very high.
  • This is an indicator of overfitting.

Accuracy

  • We are getting good accuracy for training set.
  • But for validation accuracy, it has less values for all epochs.
  • For test set, we are getting accuracy of .729. This means that 72.9 % of images are predicted correctly by the model.

Weights

  • The best set of weights seems to correspond to epoch 4, where val_accuracy is the highest (0.752) and val_loss is relatively low compared to other epochs (1.298726).

Model 2 - Fine Tuning with vgg16¶

In [ ]:
conv_base = keras.applications.vgg16.VGG16(
    weights="imagenet",
    include_top=False,
    input_shape=(180, 180, 3))
Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/vgg16/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5
58889256/58889256 [==============================] - 11s 0us/step
In [ ]:
conv_base.summary()
Model: "vgg16"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_2 (InputLayer)        [(None, 180, 180, 3)]     0         
                                                                 
 block1_conv1 (Conv2D)       (None, 180, 180, 64)      1792      
                                                                 
 block1_conv2 (Conv2D)       (None, 180, 180, 64)      36928     
                                                                 
 block1_pool (MaxPooling2D)  (None, 90, 90, 64)        0         
                                                                 
 block2_conv1 (Conv2D)       (None, 90, 90, 128)       73856     
                                                                 
 block2_conv2 (Conv2D)       (None, 90, 90, 128)       147584    
                                                                 
 block2_pool (MaxPooling2D)  (None, 45, 45, 128)       0         
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_2 (InputLayer)        [(None, 180, 180, 3)]     0         
                                                                 
 block1_conv1 (Conv2D)       (None, 180, 180, 64)      1792      
                                                                 
 block1_conv2 (Conv2D)       (None, 180, 180, 64)      36928     
                                                                 
 block1_pool (MaxPooling2D)  (None, 90, 90, 64)        0         
                                                                 
 block2_conv1 (Conv2D)       (None, 90, 90, 128)       73856     
                                                                 
 block2_conv2 (Conv2D)       (None, 90, 90, 128)       147584    
                                                                 
 block2_pool (MaxPooling2D)  (None, 45, 45, 128)       0         
                                                                 
 block3_conv1 (Conv2D)       (None, 45, 45, 256)       295168    
                                                                 
 block3_conv2 (Conv2D)       (None, 45, 45, 256)       590080    
                                                                 
 block3_conv3 (Conv2D)       (None, 45, 45, 256)       590080    
                                                                 
 block3_pool (MaxPooling2D)  (None, 22, 22, 256)       0         
                                                                 
 block4_conv1 (Conv2D)       (None, 22, 22, 512)       1180160   
                                                                 
 block4_conv2 (Conv2D)       (None, 22, 22, 512)       2359808   
                                                                 
 block4_conv3 (Conv2D)       (None, 22, 22, 512)       2359808   
                                                                 
 block4_pool (MaxPooling2D)  (None, 11, 11, 512)       0         
                                                                 
 block5_conv1 (Conv2D)       (None, 11, 11, 512)       2359808   
                                                                 
 block5_conv2 (Conv2D)       (None, 11, 11, 512)       2359808   
                                                                 
 block5_conv3 (Conv2D)       (None, 11, 11, 512)       2359808   
                                                                 
 block5_pool (MaxPooling2D)  (None, 5, 5, 512)         0         
                                                                 
=================================================================
Total params: 14,714,688
Trainable params: 14,714,688
Non-trainable params: 0
_________________________________________________________________

Preprocessing the input¶

In [ ]:
import numpy as np

def get_features_and_labels(dataset):
    all_features = []
    all_labels = []
    for images, labels in dataset:
        preprocessed_images = keras.applications.vgg16.preprocess_input(images)
        features = conv_base.predict(preprocessed_images)
        all_features.append(features)
        all_labels.append(labels)
    return np.concatenate(all_features), np.concatenate(all_labels)

train_features, train_labels =  get_features_and_labels(train_dataset)
val_features, val_labels =  get_features_and_labels(validation_dataset)
test_features, test_labels =  get_features_and_labels(test_dataset)
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 1s 608ms/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 4s 4s/step
1/1 [==============================] - 2s 2s/step
1/1 [==============================] - 3s 3s/step
1/1 [==============================] - 1s 1s/step

Freezing the model weights¶

In [ ]:
conv_base.trainable = False
conv_base.summary(
)
Model: "vgg16"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_2 (InputLayer)        [(None, 180, 180, 3)]     0         
                                                                 
 block1_conv1 (Conv2D)       (None, 180, 180, 64)      1792      
                                                                 
 block1_conv2 (Conv2D)       (None, 180, 180, 64)      36928     
                                                                 
 block1_pool (MaxPooling2D)  (None, 90, 90, 64)        0         
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_2 (InputLayer)        [(None, 180, 180, 3)]     0         
                                                                 
 block1_conv1 (Conv2D)       (None, 180, 180, 64)      1792      
                                                                 
 block1_conv2 (Conv2D)       (None, 180, 180, 64)      36928     
                                                                 
 block1_pool (MaxPooling2D)  (None, 90, 90, 64)        0         
                                                                 
 block2_conv1 (Conv2D)       (None, 90, 90, 128)       73856     
                                                                 
 block2_conv2 (Conv2D)       (None, 90, 90, 128)       147584    
                                                                 
 block2_pool (MaxPooling2D)  (None, 45, 45, 128)       0         
                                                                 
 block3_conv1 (Conv2D)       (None, 45, 45, 256)       295168    
                                                                 
 block3_conv2 (Conv2D)       (None, 45, 45, 256)       590080    
                                                                 
 block3_conv3 (Conv2D)       (None, 45, 45, 256)       590080    
                                                                 
 block3_pool (MaxPooling2D)  (None, 22, 22, 256)       0         
                                                                 
 block4_conv1 (Conv2D)       (None, 22, 22, 512)       1180160   
                                                                 
 block4_conv2 (Conv2D)       (None, 22, 22, 512)       2359808   
                                                                 
 block4_conv3 (Conv2D)       (None, 22, 22, 512)       2359808   
                                                                 
 block4_pool (MaxPooling2D)  (None, 11, 11, 512)       0         
                                                                 
 block5_conv1 (Conv2D)       (None, 11, 11, 512)       2359808   
                                                                 
 block5_conv2 (Conv2D)       (None, 11, 11, 512)       2359808   
                                                                 
 block5_conv3 (Conv2D)       (None, 11, 11, 512)       2359808   
                                                                 
 block5_pool (MaxPooling2D)  (None, 5, 5, 512)         0         
                                                                 
=================================================================
Total params: 14,714,688
Trainable params: 0
Non-trainable params: 14,714,688
_________________________________________________________________

Create Model with Convolutional base¶

In [ ]:
data_augmentation = keras.Sequential(
    [
        layers.RandomFlip("horizontal"),
        layers.RandomRotation(0.1),
        layers.RandomZoom(0.2),
    ]
)

inputs = keras.Input(shape=(180, 180, 3))
x = data_augmentation(inputs)
x = keras.applications.vgg16.preprocess_input(x)
x = conv_base(x)
x = layers.Flatten()(x)
x = layers.Dense(256)(x)
x = layers.Dropout(0.5)(x)
outputs = layers.Dense(1, activation="sigmoid")(x)
model_2 = keras.Model(inputs, outputs)
In [ ]:
model_2.summary()
Model: "model_2"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_4 (InputLayer)        [(None, 180, 180, 3)]     0         
                                                                 
 sequential_1 (Sequential)   (None, 180, 180, 3)       0         
                                                                 
 tf.__operators__.getitem_1   (None, 180, 180, 3)      0         
 (SlicingOpLambda)                                               
                                                                 
 tf.nn.bias_add_1 (TFOpLambd  (None, 180, 180, 3)      0         
 a)                                                              
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_4 (InputLayer)        [(None, 180, 180, 3)]     0         
                                                                 
 sequential_1 (Sequential)   (None, 180, 180, 3)       0         
                                                                 
 tf.__operators__.getitem_1   (None, 180, 180, 3)      0         
 (SlicingOpLambda)                                               
                                                                 
 tf.nn.bias_add_1 (TFOpLambd  (None, 180, 180, 3)      0         
 a)                                                              
                                                                 
 vgg16 (Functional)          (None, 5, 5, 512)         14714688  
                                                                 
 flatten_2 (Flatten)         (None, 12800)             0         
                                                                 
 dense_3 (Dense)             (None, 256)               3277056   
                                                                 
 dropout_1 (Dropout)         (None, 256)               0         
                                                                 
 dense_4 (Dense)             (None, 1)                 257       
                                                                 
=================================================================
Total params: 17,992,001
Trainable params: 3,277,313
Non-trainable params: 14,714,688
_________________________________________________________________
In [ ]:
model_2.compile(loss="binary_crossentropy",
              optimizer="rmsprop",
              metrics=["accuracy"])


checkpoint_filepath = 'best_model.hdf5' 

callbacks = [
    keras.callbacks.ModelCheckpoint(
        filepath=checkpoint_filepath,
        save_best_only=True,
        monitor="val_loss",
        mode='min')]
In [ ]:
history_2 = model_2.fit(
    train_dataset,
    epochs=50,
    validation_data=validation_dataset,
    callbacks=callbacks)
Epoch 1/50
63/63 [==============================] - 255s 4s/step - loss: 18.5507 - accuracy: 0.8995 - val_loss: 6.2611 - val_accuracy: 0.9570
Epoch 2/50
63/63 [==============================] - 242s 4s/step - loss: 6.5969 - accuracy: 0.9430 - val_loss: 5.9659 - val_accuracy: 0.9680
Epoch 3/50
63/63 [==============================] - 273s 4s/step - loss: 5.4062 - accuracy: 0.9565 - val_loss: 3.3580 - val_accuracy: 0.9790
Epoch 4/50
63/63 [==============================] - 231s 4s/step - loss: 4.3760 - accuracy: 0.9645 - val_loss: 5.3678 - val_accuracy: 0.9700
Epoch 5/50
63/63 [==============================] - 216s 3s/step - loss: 3.4563 - accuracy: 0.9675 - val_loss: 3.8726 - val_accuracy: 0.9720
Epoch 6/50
63/63 [==============================] - 237s 4s/step - loss: 4.8383 - accuracy: 0.9610 - val_loss: 4.1494 - val_accuracy: 0.9790
Epoch 7/50
63/63 [==============================] - 277s 4s/step - loss: 3.2910 - accuracy: 0.9675 - val_loss: 3.3694 - val_accuracy: 0.9770
Epoch 8/50
63/63 [==============================] - 294s 5s/step - loss: 3.2692 - accuracy: 0.9685 - val_loss: 3.5386 - val_accuracy: 0.9760
Epoch 9/50
63/63 [==============================] - 291s 5s/step - loss: 2.0611 - accuracy: 0.9765 - val_loss: 2.7030 - val_accuracy: 0.9830
Epoch 10/50
63/63 [==============================] - 292s 5s/step - loss: 2.5690 - accuracy: 0.9740 - val_loss: 2.2225 - val_accuracy: 0.9840
Epoch 11/50
63/63 [==============================] - 292s 5s/step - loss: 2.2632 - accuracy: 0.9710 - val_loss: 2.2174 - val_accuracy: 0.9830
Epoch 12/50
63/63 [==============================] - 289s 5s/step - loss: 2.3296 - accuracy: 0.9745 - val_loss: 2.2874 - val_accuracy: 0.9800
Epoch 13/50
63/63 [==============================] - 290s 5s/step - loss: 1.3403 - accuracy: 0.9855 - val_loss: 2.3212 - val_accuracy: 0.9790
Epoch 14/50
63/63 [==============================] - 290s 5s/step - loss: 2.2995 - accuracy: 0.9775 - val_loss: 2.5218 - val_accuracy: 0.9780
Epoch 15/50
63/63 [==============================] - 291s 5s/step - loss: 2.0498 - accuracy: 0.9740 - val_loss: 2.1650 - val_accuracy: 0.9790
Epoch 16/50
63/63 [==============================] - 307s 5s/step - loss: 1.0529 - accuracy: 0.9815 - val_loss: 1.9175 - val_accuracy: 0.9780
Epoch 17/50
63/63 [==============================] - 293s 5s/step - loss: 1.8027 - accuracy: 0.9755 - val_loss: 5.1194 - val_accuracy: 0.9670
Epoch 18/50
63/63 [==============================] - 290s 5s/step - loss: 1.2299 - accuracy: 0.9810 - val_loss: 1.5622 - val_accuracy: 0.9830
Epoch 19/50
63/63 [==============================] - 290s 5s/step - loss: 0.7268 - accuracy: 0.9855 - val_loss: 2.3659 - val_accuracy: 0.9760
Epoch 20/50
63/63 [==============================] - 291s 5s/step - loss: 0.8653 - accuracy: 0.9865 - val_loss: 2.3768 - val_accuracy: 0.9800
Epoch 21/50
63/63 [==============================] - 290s 5s/step - loss: 1.3966 - accuracy: 0.9785 - val_loss: 1.7610 - val_accuracy: 0.9790
Epoch 22/50
63/63 [==============================] - 289s 5s/step - loss: 1.0984 - accuracy: 0.9825 - val_loss: 2.4212 - val_accuracy: 0.9770
Epoch 23/50
63/63 [==============================] - 290s 5s/step - loss: 0.9518 - accuracy: 0.9815 - val_loss: 2.0234 - val_accuracy: 0.9790
Epoch 24/50
63/63 [==============================] - 289s 5s/step - loss: 0.8975 - accuracy: 0.9865 - val_loss: 2.0105 - val_accuracy: 0.9780
Epoch 25/50
63/63 [==============================] - 289s 5s/step - loss: 0.6552 - accuracy: 0.9885 - val_loss: 2.1820 - val_accuracy: 0.9760
Epoch 26/50
63/63 [==============================] - 289s 5s/step - loss: 0.4651 - accuracy: 0.9880 - val_loss: 2.1535 - val_accuracy: 0.9780
Epoch 27/50
63/63 [==============================] - 290s 5s/step - loss: 0.7569 - accuracy: 0.9865 - val_loss: 2.0905 - val_accuracy: 0.9800
Epoch 28/50
63/63 [==============================] - 286s 5s/step - loss: 0.9833 - accuracy: 0.9825 - val_loss: 2.2268 - val_accuracy: 0.9800
Epoch 29/50
63/63 [==============================] - 288s 5s/step - loss: 0.7433 - accuracy: 0.9860 - val_loss: 2.7026 - val_accuracy: 0.9770
Epoch 30/50
63/63 [==============================] - 293s 5s/step - loss: 0.9471 - accuracy: 0.9830 - val_loss: 2.0925 - val_accuracy: 0.9790
Epoch 31/50
63/63 [==============================] - 289s 5s/step - loss: 0.3297 - accuracy: 0.9945 - val_loss: 2.3164 - val_accuracy: 0.9770
Epoch 32/50
63/63 [==============================] - 286s 5s/step - loss: 1.0803 - accuracy: 0.9830 - val_loss: 2.1292 - val_accuracy: 0.9830
Epoch 33/50
63/63 [==============================] - 289s 5s/step - loss: 0.7320 - accuracy: 0.9855 - val_loss: 2.0574 - val_accuracy: 0.9790
Epoch 34/50
63/63 [==============================] - 287s 5s/step - loss: 0.4860 - accuracy: 0.9910 - val_loss: 1.8950 - val_accuracy: 0.9820
Epoch 35/50
63/63 [==============================] - 288s 5s/step - loss: 0.6043 - accuracy: 0.9885 - val_loss: 1.8690 - val_accuracy: 0.9830
Epoch 36/50
63/63 [==============================] - 287s 5s/step - loss: 0.6052 - accuracy: 0.9870 - val_loss: 1.6292 - val_accuracy: 0.9810
Epoch 37/50
63/63 [==============================] - 288s 5s/step - loss: 0.9456 - accuracy: 0.9830 - val_loss: 1.8927 - val_accuracy: 0.9800
Epoch 38/50
63/63 [==============================] - 288s 5s/step - loss: 0.5197 - accuracy: 0.9855 - val_loss: 1.6955 - val_accuracy: 0.9820
Epoch 39/50
63/63 [==============================] - 289s 5s/step - loss: 0.6802 - accuracy: 0.9845 - val_loss: 2.3554 - val_accuracy: 0.9810
Epoch 40/50
63/63 [==============================] - 291s 5s/step - loss: 0.7947 - accuracy: 0.9845 - val_loss: 2.0510 - val_accuracy: 0.9790
Epoch 41/50
63/63 [==============================] - 290s 5s/step - loss: 0.6071 - accuracy: 0.9880 - val_loss: 1.8148 - val_accuracy: 0.9790
Epoch 42/50
63/63 [==============================] - 291s 5s/step - loss: 0.4787 - accuracy: 0.9890 - val_loss: 4.8375 - val_accuracy: 0.9620
Epoch 43/50
63/63 [==============================] - 293s 5s/step - loss: 0.8638 - accuracy: 0.9835 - val_loss: 2.2905 - val_accuracy: 0.9770
Epoch 44/50
63/63 [==============================] - 294s 5s/step - loss: 0.4971 - accuracy: 0.9880 - val_loss: 3.5240 - val_accuracy: 0.9690
Epoch 45/50
63/63 [==============================] - 288s 5s/step - loss: 0.4974 - accuracy: 0.9890 - val_loss: 1.7036 - val_accuracy: 0.9800
Epoch 46/50
63/63 [==============================] - 288s 5s/step - loss: 0.2960 - accuracy: 0.9910 - val_loss: 2.5766 - val_accuracy: 0.9770
Epoch 47/50
63/63 [==============================] - 287s 5s/step - loss: 0.3670 - accuracy: 0.9920 - val_loss: 2.9472 - val_accuracy: 0.9760
Epoch 48/50
63/63 [==============================] - 288s 5s/step - loss: 0.3266 - accuracy: 0.9910 - val_loss: 1.8827 - val_accuracy: 0.9780
Epoch 49/50
63/63 [==============================] - 286s 5s/step - loss: 0.6584 - accuracy: 0.9890 - val_loss: 2.1387 - val_accuracy: 0.9780
Epoch 50/50
63/63 [==============================] - 288s 5s/step - loss: 0.4668 - accuracy: 0.9900 - val_loss: 1.6586 - val_accuracy: 0.9800
In [ ]:
acc = history_2.history["accuracy"]
val_acc = history_2.history["val_accuracy"]
loss = history_2.history["loss"]
val_loss = history_2.history["val_loss"]
epochs = range(1, len(acc) + 1)
plt.plot(epochs, acc, "bo", label="Training accuracy")
plt.plot(epochs, val_acc, "b", label="Validation accuracy")
plt.title("Training and validation accuracy")
plt.legend()
plt.figure()
plt.plot(epochs, loss, "bo", label="Training loss")
plt.plot(epochs, val_loss, "b", label="Validation loss")
plt.title("Training and validation loss")
plt.legend()
plt.show()

Evaluate the model with test set¶

In [ ]:
test_model_2 = keras.models.load_model(
    "best_model.hdf5")
test_loss_2, test_acc_2 = test_model_2.evaluate(test_dataset)
print(f"Test accuracy: {test_acc_2:.3f}")
63/63 [==============================] - 194s 3s/step - loss: 2.4849 - accuracy: 0.9765
Test accuracy: 0.976
In [ ]:
history_2_dict = history_2.history
hist_df_2 = pd.DataFrame(history_2_dict)
hist_df_2
Out[ ]:
loss accuracy val_loss val_accuracy
0 18.550718 0.8995 6.261053 0.957
1 6.596909 0.9430 5.965850 0.968
2 5.406242 0.9565 3.357971 0.979
3 4.376008 0.9645 5.367783 0.970
4 3.456275 0.9675 3.872593 0.972
5 4.838308 0.9610 4.149443 0.979
6 3.291010 0.9675 3.369395 0.977
7 3.269237 0.9685 3.538553 0.976
8 2.061107 0.9765 2.702962 0.983
9 2.568978 0.9740 2.222455 0.984
10 2.263160 0.9710 2.217408 0.983
11 2.329571 0.9745 2.287379 0.980
12 1.340334 0.9855 2.321165 0.979
13 2.299511 0.9775 2.521809 0.978
14 2.049802 0.9740 2.165018 0.979
15 1.052905 0.9815 1.917543 0.978
16 1.802688 0.9755 5.119412 0.967
17 1.229874 0.9810 1.562165 0.983
18 0.726829 0.9855 2.365862 0.976
19 0.865333 0.9865 2.376798 0.980
20 1.396641 0.9785 1.760978 0.979
21 1.098444 0.9825 2.421160 0.977
22 0.951769 0.9815 2.023438 0.979
23 0.897475 0.9865 2.010543 0.978
24 0.655156 0.9885 2.181980 0.976
25 0.465060 0.9880 2.153502 0.978
26 0.756925 0.9865 2.090546 0.980
27 0.983262 0.9825 2.226842 0.980
28 0.743338 0.9860 2.702588 0.977
29 0.947119 0.9830 2.092499 0.979
30 0.329667 0.9945 2.316390 0.977
31 1.080271 0.9830 2.129171 0.983
32 0.731980 0.9855 2.057376 0.979
33 0.485960 0.9910 1.895024 0.982
34 0.604330 0.9885 1.869005 0.983
35 0.605171 0.9870 1.629161 0.981
36 0.945603 0.9830 1.892708 0.980
37 0.519740 0.9855 1.695460 0.982
38 0.680225 0.9845 2.355415 0.981
39 0.794716 0.9845 2.050990 0.979
40 0.607126 0.9880 1.814754 0.979
41 0.478695 0.9890 4.837509 0.962
42 0.863818 0.9835 2.290490 0.977
43 0.497062 0.9880 3.523992 0.969
44 0.497401 0.9890 1.703560 0.980
45 0.296035 0.9910 2.576616 0.977
46 0.367049 0.9920 2.947249 0.976
47 0.326603 0.9910 1.882694 0.978
48 0.658422 0.9890 2.138710 0.978
49 0.466835 0.9900 1.658611 0.980

Conclusions¶

Training & Validation loss

  • This model performs well on the training data and validation data.
  • This model shows a best fit.
  • The gap between validation and training loss is very low.
  • This is an indicator of best fit model.

Accuracy

  • We are getting good accuracy for training set and validation set.
  • The accuracy on test set is .976.
  • This means that 97.6 % of the images are correctly predicted by the model.

Weights

  • The best set of weights seems to correspond to epoch 35, where val_accuracy is the highest (0.981) and val_loss is relatively low compared to other epochs (1.629161).

Summarised Conclusion is give below

Model Name Highest Val Accuracy Val_Loss Epoch
Model_1 0.752 1.298726 4
Model_2 Fine Tuning 0.981 1.629161 35

Accuracy for test set | Model Name | Accuracy | |------------|----------------------| | Model_1 | 0.729 | | Model_2 Fine Tuning | 0.976|

Relative performance of the models¶

I am using ImageDatagenerator in this step to get lables and features for validation dataset.

In [ ]:
import os
import numpy as np
from keras.preprocessing.image import ImageDataGenerator
from keras.models import load_model
from sklearn.metrics import accuracy_score, confusion_matrix, classification_report, precision_recall_curve
import matplotlib.pyplot as plt

validation_dir = 'datacats_and_dogs_small/validation'

img_height, img_width = 180, 180  
batch_size = 32  
validation_image_generator = ImageDataGenerator(rescale=1./255)

val_data_gen   = validation_image_generator.flow_from_directory(
                    validation_dir,
                    target_size=(img_height, img_width),
                    batch_size=batch_size,
                    class_mode='binary')
Found 1000 images belonging to 2 classes.

Model 1¶

Accuracy

In [ ]:
# Load the best model
model1_new = load_model('best_model_model1.hdf5')
y_pred_model1 = model1_new.predict(val_data_gen)
y_pred_class_model1 = np.round(y_pred_model1).astype(int)
validation_labels = val_data_gen.classes

accuracy_model1 = accuracy_score(validation_labels, y_pred_class_model1)
print("Accuracy - Model 1:", accuracy_model1)
32/32 [==============================] - 12s 385ms/step
Accuracy - Model 1: 0.5

Confusion Matrix

In [ ]:
# Confusion matrix
conf_matrix_model1 = confusion_matrix(validation_labels, y_pred_class_model1)
sns.heatmap(conf_matrix_model1, annot=True, fmt='d', cmap='Blues')
Out[ ]:
<Axes: >

Precision, Recall, F1-Score

In [ ]:
# Generate classification report
report = classification_report(validation_labels, y_pred_class_model1, output_dict=True)

# Convert report to pandas DataFrame
report_df = pd.DataFrame(report).transpose()

# Display the report
display(report_df)
precision recall f1-score support
0 0.50 1.0 0.666667 500.0
1 0.00 0.0 0.000000 500.0
accuracy 0.50 0.5 0.500000 0.5
macro avg 0.25 0.5 0.333333 1000.0
weighted avg 0.25 0.5 0.333333 1000.0

Precision-Recall Curve

In [ ]:
# Precision-Recall curve
precision_model1, recall_model1, _ = precision_recall_curve(validation_labels, y_pred_model1)
plt.plot(recall_model1, precision_model1, label='Model 1')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title('Precision-Recall Curve')
plt.legend()
plt.show()

Model 2¶

Accuracy

In [ ]:
# Load the best model
model2_new = load_model('best_model.hdf5')
y_pred_model2 = model2_new.predict(val_data_gen)
y_pred_class_model2 = np.round(y_pred_model2).astype(int)

accuracy_model2 = accuracy_score(validation_labels, y_pred_class_model2)
print("Accuracy - Model 2:", accuracy_model2)
63/63 [==============================] - 209s 3s/step
Accuracy - Model 2: 0.5

Confusion matrix

In [ ]:
# Confusion matrix
conf_matrix_model2 = confusion_matrix(validation_labels, y_pred_class_model2)
sns.heatmap(conf_matrix_model2, annot=True, fmt='d', cmap='Blues')
Out[ ]:
<Axes: >
In [ ]:
# Generate classification report
report_2 = classification_report(validation_labels, y_pred_class_model2, output_dict=True)

# Convert report to pandas DataFrame
report_df_2 = pd.DataFrame(report_2).transpose()

# Display the report
display(report_df_2)
precision recall f1-score support
0 0.50 1.0 0.666667 500.0
1 0.00 0.0 0.000000 500.0
accuracy 0.50 0.5 0.500000 0.5
macro avg 0.25 0.5 0.333333 1000.0
weighted avg 0.25 0.5 0.333333 1000.0
In [ ]:
# Precision-Recall curve
precision_model2, recall_model2, _ = precision_recall_curve(validation_labels, y_pred_model2)
plt.plot(recall_model2, precision_model2, label='Model 2')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title('Precision-Recall Curve')
plt.legend()
plt.show()

Conclusions¶

  • Fine tuning with vgg16 has good accuracy in test set.
  • It has a accuracy of .976 fo test set.
  • That means the model is able to predict 97.6 % of images correctly.
  • So Model 2 (vgg16) is the good model.